#!/usr/bin/python

#imports
import string
import sys
import math

#Globals
form_dict = {'?pagewidth': 0,\
             '?margin' : 0,\
             '?mode' : 'unfilled',\
             '?columns' : 0,\
             '?colwidth' : 0}

def set_format(line):
    """Checks if line is a formatting command.
    
    Inputs:
        Arguments:
            line        - A string to be checked.
        Globals:
            form_dict   - Holds formatting Commands.
    Outputs:
        Globals:
            form_dict   - If a formating option is changed
                          the dictionary entry will be updated
        Returns:
            True        - If the line was a formatting command
            False       - If the line is not a formatting command
    
    """
    global form_dict
    tmp = line.split()
    fmat = tmp[0]
    # Default mode is unfilled mode becomes filled
    # when a ?pagewidth command is given.
    if fmat == '?pagewidth':
        form_dict['?mode'] = 'filled'
    if fmat in form_dict:
        num = tmp[1]
        # Checks if the ?mode command has been given
        if fmat == "?mode":
            form_dict[fmat] = num
            return True
        cur = int(form_dict[fmat])
        delta = 0
        if num[0] == '+':
            delta = int(num[1:])
            form_dict[fmat] = cur + delta
            # Makes sure if the margin was changed that is isn't
            # bigger than pagewidth minus 20
            if form_dict["?margin"] > form_dict["?pagewidth"] - 20:
                form_dict["?margin"] = form_dict["?pagewidth"] - 20
        elif num[0] == '-':
            # Makes sure margin isn't less than 0
            delta = int(num[1:])
            if cur - delta > 0:
                form_dict[fmat] = cur - delta
            else:
                form_dict[fmat] = 0
        else:
            form_dict[fmat] = int(num)
        return True
    return False

def margin():
    """Creates a margin of a given width.

    Inputs:
        Globals:
            form_dict
        Arguments:
            None
    Outputs:
        Returns:
            Margin
        Globals:
            None
    """
    return (' ' * form_dict['?margin'])

def split_list(li):
    """Spits input into as many lists as there is columns

    Inputs:
        Arguments:
            li          - list to be split
        Globals:
            form_dict   - to get the number of columns
    Outputs:
        Returns:
            li          - Generator of list size len(li)/n
    """
    n = form_dict['?columns']
    n = int(math.ceil(len(li)/float(n)))
    for i in xrange(0,len(li),n):
        yield li[i:i+n]

def print_formated(text):
    """Holds the logic for printing the lines
    
    Inputs:
        Arguments:
            text        - Iterable object of strings to be 
                          formatted
        Globals:
            form_dict   - Holds Print Columns info
    Outputs:
        Returns:
            None
        Effects:
            Prints formatted text to stdout
    """
    formatted = format_string_list(text)
    # Checks if Columns mode
    if form_dict['?columns'] >= 2:
        chunks = list(split_list(formatted))
        for i in xrange(len(chunks[0])):
            for j in xrange(len(chunks)):
                try:
                    l = chunks[j][i]
                    x = form_dict['?pagewidth'] -\
                        len(l.decode('utf-8'))+ form_dict['?colwidth']
                    # Checks if the last column is being printed
                    sys.stdout.write(l + " "*x)
                except:
                    pass
            print
    # Otherwise prints the formatted file to stdout
    else:
        for line in formatted:
            print line

def format_string_list(text):
    """Formats text based on the texts internal formatting options.

    Inputs:
        Arguments:
            text        - an iterable object containing strings
        Globals:
            form_dict   - used to check current formatting options
    Outputs:
        Returns:
            li          - Iterable formatted list of strings
        Globals:
            None
    Notes:
        None
    """
    tmp = None
    string = ''
    li = []
    for line in text:
        tmp = line.split()
        if len(tmp) != 0 and set_format(line):
            continue
        if form_dict['?mode'] == 'unfilled':
            # [:-1] to remove the lines \n
            li.append(line[:-1])
            continue
        if len(tmp) == 0:
            if len(string) == 0:
                li.append('')
            else:
                li.append(string[:-1])
                li.append('')
            string = ''
            continue
        if  len(string) == 0:
            string = string + margin()
            cur_width = form_dict['?margin']
        for word in tmp:
            if len(string)+len(word)  > form_dict['?pagewidth']:
                li.append(string[:-1])
                string = ''
            if len(string) != 0:
                string = string + word + ' '
            else:
                string = string + margin() + word + ' '
    if len(string) != 0 and form_dict['?mode'] == 'filled':
        li.append(string[:-1])
    return li

def get_input():
    """This function gets the input.
    
    Inputs:
        None
    Outputs:
        Returns:
            text - refences a file, or stdin.
    Notes:
        if the args are given wrong 
        the script will exit. 
    """
    text = None
    if (len(sys.argv) == 2):
         t_file = sys.argv[1]
         text = open(t_file,'r')
    elif (len(sys.argv) == 1):
         text = sys.stdin
    else:
         print "Wrong Inputs Brah"
         sys.exit()
    return text

def main():
    text = get_input()
    print_formated(text)
    
if __name__ == "__main__":
    main()
